<template>
  <el-container class="panel-container">
    <el-tabs v-model="activeTab" style="height: 100%; overflow: hidden">
      <el-tab-pane :label="i18nt('designer.hint.widgetSetting')" name="1">
        <el-scrollbar class="setting-scrollbar" :style="{ height: scrollerHeight }">
          <template v-if="!!designer.selectedWidget && !designer.selectedWidget.category">
            <el-form
              :model="optionModel"
              size="small"
              label-position="left"
              label-width="120px"
              class="setting-form"
              @submit.prevent
            >
              <el-collapse v-model="widgetActiveCollapseNames" class="setting-collapse">
                <el-collapse-item
                  name="1"
                  v-if="showCollapse(commonProps)"
                  :title="i18nt('designer.setting.commonSetting')"
                >
                  <template
                    v-for="(editorName, propName) in commonProps"
                    :key="editorName + propName"
                  >
                    <component
                      v-if="hasPropEditor(propName, editorName)"
                      :is="getPropEditor(propName, editorName)"
                      :designer="designer"
                      :selected-widget="selectedWidget"
                      :option-model="optionModel"
                      @update:option-model="optionModel = $event"
                      @update:form-config="localFormConfig = $event"
                      @update:designer="localDesigner = $event"
                      @update:selected-widget="localSelectedWidget = $event"
                    />
                  </template>
                </el-collapse-item>

                <el-collapse-item
                  name="2"
                  v-if="showCollapse(advProps)"
                  :title="i18nt('designer.setting.advancedSetting')"
                >
                  <template v-for="(editorName, propName) in advProps" :key="editorName + propName">
                    <component
                      v-if="hasPropEditor(propName, editorName)"
                      :is="getPropEditor(propName, editorName)"
                      :designer="designer"
                      :selected-widget="selectedWidget"
                      :option-model="optionModel"
                      @update:option-model="optionModel = $event"
                      @update:form-config="localFormConfig = $event"
                      @update:designer="localDesigner = $event"
                      @update:selected-widget="localSelectedWidget = $event"
                    />
                  </template>
                </el-collapse-item>

                <EventSettingPanel
                  :selected-widget="selectedWidget"
                  @update:selected-widget="localSelectedWidget = $event"
                />
              </el-collapse>
            </el-form>
          </template>

          <template v-if="!!designer.selectedWidget && !!designer.selectedWidget.category">
            <el-form
              :model="optionModel"
              size="small"
              label-position="left"
              label-width="120px"
              class="setting-form"
              @submit.prevent
            >
              <el-collapse v-model="widgetActiveCollapseNames" class="setting-collapse">
                <el-collapse-item
                  name="1"
                  v-if="showCollapse(commonProps)"
                  :title="i18nt('designer.setting.commonSetting')"
                >
                  <template
                    v-for="(editorName, propName) in commonProps"
                    :key="editorName + propName"
                  >
                    <component
                      v-if="hasPropEditor(propName, editorName)"
                      :is="getPropEditor(propName, editorName)"
                      :designer="designer"
                      :selected-widget="selectedWidget"
                      :option-model="optionModel"
                      @update:option-model="optionModel = $event"
                      @update:form-config="localFormConfig = $event"
                      @update:designer="localDesigner = $event"
                      @update:selected-widget="localSelectedWidget = $event"
                    />
                  </template>
                </el-collapse-item>

                <el-collapse-item
                  name="2"
                  v-if="showCollapse(advProps)"
                  :title="i18nt('designer.setting.advancedSetting')"
                >
                  <template v-for="(editorName, propName) in advProps" :key="editorName + propName">
                    <component
                      v-if="hasPropEditor(propName, editorName)"
                      :is="getPropEditor(propName, editorName)"
                      :designer="designer"
                      :selected-widget="selectedWidget"
                      :option-model="optionModel"
                      @update:option-model="optionModel = $event"
                      @update:form-config="localFormConfig = $event"
                      @update:designer="localDesigner = $event"
                      @update:selected-widget="localSelectedWidget = $event"
                    />
                  </template>
                </el-collapse-item>

                <el-collapse-item
                  name="3"
                  v-if="showEventCollapse() && showCollapse(eventProps)"
                  :title="i18nt('designer.setting.eventSetting')"
                >
                  <template
                    v-for="(editorName, propName) in eventProps"
                    :key="editorName + propName"
                  >
                    <component
                      v-if="hasPropEditor(propName, editorName)"
                      :is="getPropEditor(propName, editorName)"
                      :designer="designer"
                      :selected-widget="selectedWidget"
                      :option-model="optionModel"
                      @update:option-model="optionModel = $event"
                      @update:form-config="localFormConfig = $event"
                      @update:designer="localDesigner = $event"
                      @update:selected-widget="localSelectedWidget = $event"
                    />
                  </template>
                </el-collapse-item>
              </el-collapse>
            </el-form>
          </template>
        </el-scrollbar>
      </el-tab-pane>

      <el-tab-pane v-if="!!designer" :label="i18nt('designer.hint.formSetting')" name="2">
        <el-scrollbar class="setting-scrollbar" :style="{ height: scrollerHeight }">
          <form-setting
            :designer="designer"
            :form-config="formConfig"
            @update:form-config="localFormConfig = $event"
            @update:designer="localDesigner = $event"
          />
        </el-scrollbar>
      </el-tab-pane>
      <el-tab-pane label="数据源" name="3">
        <el-table :data="dbList" style="width: 100%" max-height="250">
          <el-table-column fixed prop="tableName" label="名称" width="150" />
          <el-table-column fixed="right" label="操作" width="120">
            <template #default="scope">
              <el-button
                circle
                style="color: red; border: none"
                icon="el-icon-delete"
                @click.prevent="delDbList(scope.$index)"
              />
            </template>
          </el-table-column>
        </el-table>
        <div class="databaseDiv">
          <el-button
            class="mt-4"
            style="width: 100%"
            @click="centerDialogVisible = true"
            type="primary"
            >绑定模型</el-button
          >
          <el-dialog v-model="centerDialogVisible" title="选择模型" width="500" align-center>
            <el-form :rules="rules" :model="formSchema">
              <el-form-item label="模型" prop="modelName">
                <el-select
                  v-model="formSchema.modelId"
                  filterable
                  remote
                  reserve-keyword
                  placeholder="选择模型"
                  :remote-method="remoteMethod"
                  :loading="loading"
                  @change="modelChange"
                  style="width: 240px"
                >
                  <el-option
                    v-for="item in options"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                  />
                  <template #loading>
                    <svg class="circular" viewBox="0 0 50 50">
                      <circle class="path" cx="25" cy="25" r="20" fill="none" />
                    </svg>
                  </template>
                </el-select>
              </el-form-item>
            </el-form>
            <template #footer>
              <div class="dialog-footer">
                <el-button @click="centerDialogVisible = false"> 取消 </el-button>
                <el-button type="primary" @click="addDbList">确定</el-button>
              </div>
            </template>
          </el-dialog>
        </div>
      </el-tab-pane>
    </el-tabs>

    <div
      v-if="showWidgetEventDialogFlag"
      class=""
      v-drag="['.drag-dialog.el-dialog', '.drag-dialog .el-dialog__header']"
    >
      <el-dialog
        :title="i18nt('designer.setting.editWidgetEventHandler')"
        v-model="showWidgetEventDialogFlag"
        :show-close="true"
        class="drag-dialog small-padding-dialog"
        append-to-body
        :close-on-click-modal="false"
        :close-on-press-escape="false"
        :destroy-on-close="true"
      >
        <el-alert type="info" :closable="false" :title="eventHeader" />
        <code-editor
          :mode="'javascript'"
          :readonly="false"
          v-model="eventHandlerCode"
          ref="ecEditor"
        />
        <el-alert type="info" :closable="false" title="}" />
        <template #footer>
          <div class="dialog-footer">
            <el-button @click="showWidgetEventDialogFlag = false">
              {{ i18nt('designer.hint.cancel') }}</el-button
            >
            <el-button type="primary" @click="saveEventHandler">
              {{ i18nt('designer.hint.confirm') }}</el-button
            >
          </div>
        </template>
      </el-dialog>
    </div>
  </el-container>
</template>

<script>
import EventSettingPanel from './eventSettingPanel.vue'
import CodeEditor from '@/components/variant-form3/code-editor/index.vue'
import PropertyEditors from './property-editor'
import FormSetting from './form-setting.vue'
import WidgetProperties from './propertyRegister'
import { getGenerateListApi } from '@/api/generate'
import { addWindowResizeHandler } from '@/utils/util'
import i18n from '@/utils/i18n'
import emitter from '@/utils/emitter'
import { propertyRegistered } from '@/components/variant-form3/form-designer/setting-panel/propertyRegister.js'
import { useForm } from '@/hooks/web/useForm'
import { useValidator } from '@/hooks/web/useValidator'
import { reactive, toRefs } from 'vue'
const { COMMON_PROPERTIES, ADVANCED_PROPERTIES, EVENT_PROPERTIES } = WidgetProperties
const { formRegister, formMethods } = useForm()
const { setValues, getFormData, getElFormExpose } = formMethods
const { required } = useValidator()
export default {
  name: 'SettingPanel',
  componentName: 'SettingPanel',
  components: {
    CodeEditor,
    FormSetting,
    EventSettingPanel,
    ...PropertyEditors
  },
  mixins: [i18n, emitter],
  inject: ['getDesignerConfig'],
  props: {
    designer: Object,
    modelName: {
      type: String,
      default: null
    },
    selectedWidget: Object,
    formConfig: Object,
    globalDsv: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
      localDesigner: this.designer,
      localFormConfig: this.formConfig,
      localSelectedWidget: this.selectedWidget,
      dbList: [],
      centerDialogVisible: false,
      loading: false,
      options: [],
      rules: {
        roleName: [required()]
      },
      formSchema: {
        modelId: '',
        modelName: ''
      },
      designerConfig: this.getDesignerConfig(),
      scrollerHeight: 0,

      activeTab: '2',
      widgetActiveCollapseNames: ['1', '3'], //['1', '2', '3'],
      formActiveCollapseNames: ['1', '2'],

      commonProps: COMMON_PROPERTIES,
      advProps: ADVANCED_PROPERTIES,
      eventProps: EVENT_PROPERTIES,

      showWidgetEventDialogFlag: false,
      eventHandlerCode: '',
      curEventName: '',
      eventHeader: '',
      subFormChildWidgetFlag: false
    }
  },
  computed: {
    optionModel: {
      get() {
        return this.localSelectedWidget.options
      },

      set(newValue) {
        this.localSelectedWidget.options = newValue
      }
    }
  },
  watch: {
    'designer.selectedWidget': {
      handler(val) {
        if (!!val) {
          this.activeTab = '1'
        }
      }
    },

    'localSelectedWidget.options': {
      //组件属性变动后，立即保存表单JSON！！
      deep: true,
      handler(newValue) {
        if (newValue !== this.selectedWidget.options) {
          this.$emit('update:selected-widget', { ...this.localSelectedWidget })
        }
        this.designer.saveCurrentHistoryStep()
      }
    },
    modelName(newValue) {
      // if (this.dbList.length == 0) {
      //   this.dbList.push({ tableName: this.modelName })
      // }
      if (this.dbList.length === 0 && newValue) {
        this.dbList.push({ tableName: newValue || '默认名称' })
      }
    },
    localDesigner(newValue) {
      this.$emit('update:designer', this.localDesigner)
    },

    // Also make sure to update the local model if the prop changes externally
    designer(newVal) {
      this.localDesigner = newVal
      this.$emit('update:designer', this.localDesigner)
    },
    localFormConfig(newValue) {
      this.$emit('update:formConfig', this.localFormConfig)
    },
    localSelectedWidget(newValue) {
      this.$emit('update:selectedWidget', this.localSelectedWidget)
      this.designer.saveCurrentHistoryStep()
    },

    // Also make sure to update the local model if the prop changes externally
    selectedWidget(newVal) {
      if (newVal) {
        this.localSelectedWidget = newVal
        this.designer.saveCurrentHistoryStep()
      }
    },
    formConfig: {
      deep: true,
      handler(newVal) {
        this.localFormConfig = newVal
        this.designer.saveCurrentHistoryStep()
      }
    }
  },
  created() {
    this.on$('editEventHandler', (eventParams) => {
      //debugger
      this.editEventHandler(eventParams[0], eventParams[1])
    })

    this.designer.handleEvent('form-css-updated', (cssClassList) => {
      this.designer.setCssClassList(cssClassList)
    })
    if (this.modelName) {
      console.log('this.modelName', this.modelName)
      this.dbList.push({ tableName: this.modelName })
    }
  },
  mounted() {
    if (!this.designer.selectedWidget) {
      this.activeTab = '2'
    } else {
      this.activeTab = '1'
    }

    this.scrollerHeight = window.innerHeight - 56 - 48 + 'px'
    addWindowResizeHandler(() => {
      this.$nextTick(() => {
        this.scrollerHeight = window.innerHeight - 56 - 48 + 'px'
        //console.log(this.scrollerHeight)
      })
    })
  },
  methods: {
    modelChange(model) {
      console.log('model', model)
    },
    delDbList(index) {
      this.dbList.splice(index, 1)
    },
    addDbList() {
      console.log('add', this.modelName)
      if (this.dbList.length === 1) {
        ElMessage.error('主表只能绑定一个数据源')
        return
      }
      let modelName = this.modelName
      console.log(this.formSchema)
      this.options.map((item) => {
        if (item.value === this.formSchema.modelId) {
          this.dbList.push({ tableName: item.label })
          modelName = item.label
        }
      })
      this.$emit('loadDataBase', { modelId: this.formSchema.modelId, modelName: modelName })
      this.formSchema.modelName = ''
      this.centerDialogVisible = false
    },
    async remoteMethod(query) {
      this.loading = true
      const res = await getGenerateListApi({ tableName: query })
      if (res.success) {
        this.options = res.result.map((item) => {
          return { label: item.tableName, value: item.id }
        })
        this.loading = false
      }
      console.log('this.options', this.options)
    },
    showEventCollapse() {
      if (this.designerConfig['eventCollapse'] === undefined) {
        return true
      }

      return !!this.designerConfig['eventCollapse']
    },

    hasPropEditor(propName, editorName) {
      if (!editorName) {
        return false
      }

      /* alert组件注册了两个type属性编辑器，跳过第一个type属性编辑器，只显示第二个alert-type属性编辑器！！ */
      if (propName.indexOf('-') <= -1) {
        let uniquePropName = this.selectedWidget.type + '-' + propName
        if (propertyRegistered(uniquePropName)) {
          return false
        }
      }

      let originalPropName = propName.replace(this.selectedWidget.type + '-', '') //去掉组件名称前缀-，如果有的话！！
      return this.designer.hasConfig(this.selectedWidget, originalPropName)
    },

    getPropEditor(propName, editorName) {
      let originalPropName = propName.replace(this.selectedWidget.type + '-', '') //去掉组件名称前缀-，如果有的话！！
      let ownPropEditorName = `${this.selectedWidget.type}-${originalPropName}-editor`
      //console.log(ownPropEditorName, this.$options.components[ownPropEditorName])
      if (!!this.$options.components[ownPropEditorName]) {
        //局部注册的属性编辑器组件
        return ownPropEditorName
      }

      //return !!this.$root.$options.components[ownPropEditorName] ? ownPropEditorName : editorName  //Vue2全局注册的属性编辑器组件
      return !!this.$root.$.appContext.components[ownPropEditorName]
        ? ownPropEditorName
        : editorName //Vue3全局注册的属性编辑器组件
    },

    showCollapse(propsObj) {
      let result = false

      for (let propName in propsObj) {
        if (!propsObj.hasOwnProperty(propName)) {
          continue
        }

        if (this.hasPropEditor(propName, propsObj[propName])) {
          result = true
          break
        }
      }

      return result
    },

    editEventHandler(eventName, eventParams) {
      //debugger

      this.curEventName = eventName
      this.eventHeader = `${this.optionModel.name}.${eventName}(${eventParams.join(', ')}) {`
      this.eventHandlerCode = this.selectedWidget.options[eventName] || ''

      // 设置字段校验函数示例代码
      if (eventName === 'onValidate' && !this.optionModel['onValidate']) {
        this.eventHandlerCode =
          "  /* sample code */\n  /*\n  if ((value > 100) || (value < 0)) {\n    callback(new Error('error message'))  //fail\n  } else {\n    callback();  //pass\n  }\n  */"
      }

      this.showWidgetEventDialogFlag = true
    },

    saveEventHandler() {
      const codeHints = this.$refs.ecEditor.getEditorAnnotations()
      let syntaxErrorFlag = false
      if (!!codeHints && codeHints.length > 0) {
        codeHints.forEach((chItem) => {
          if (chItem.type === 'error') {
            syntaxErrorFlag = true
          }
        })

        if (syntaxErrorFlag) {
          ElMessage.error(this.i18nt('designer.setting.syntaxCheckWarning'))
          return
        }
      }

      this.localSelectedWidget.options[this.curEventName] = this.eventHandlerCode
      this.showWidgetEventDialogFlag = false
    }
  }
}
</script>

<style lang="scss" scoped>
.panel-container {
  padding: 0 8px;
}

.setting-scrollbar {
  :deep(.el-scrollbar__wrap) {
    overflow-x: hidden; /* IE浏览器隐藏水平滚动条箭头！！ */
  }
}

.setting-collapse {
  :deep(.el-collapse-item__content) {
    padding-bottom: 6px;
  }

  :deep(.el-collapse-item__header) {
    font-style: italic;
    font-weight: bold;
  }
}

.setting-form {
  :deep(.el-form-item__label) {
    font-size: 13px;
    //text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
  }

  :deep(.el-form-item--small.el-form-item) {
    margin-bottom: 10px;
  }
}

/* 隐藏Chrome浏览器中el-input数字输入框右侧的上下调整小箭头 */
:deep(.hide-spin-button) input::-webkit-outer-spin-button,
:deep(.hide-spin-button) input::-webkit-inner-spin-button {
  -webkit-appearance: none !important;
}

/* 隐藏Firefox浏览器中el-input数字输入框右侧的上下调整小箭头 */
:deep(.hide-spin-button) input[type='number'] {
  -moz-appearance: textfield;
}

:deep(.custom-divider.el-divider--horizontal) {
  margin: 10px 0;
}

:deep(.custom-divider-margin-top.el-divider--horizontal) {
  margin: 20px 0;
}

.small-padding-dialog {
  :deep(.el-dialog__body) {
    padding: 6px 15px 12px 15px;
  }
}

.databaseDiv {
  height: 100%;
  display: flex;
  justify-content: center; /* 水平居中 */
  font-size: 14px;
}
</style>
